home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UTEView.cp < prev    next >
Text File  |  1991-05-01  |  66KB  |  2,408 lines

  1. // UTEView.cp
  2. // Copyright © 1984-1991 Apple Computer Inc. All rights reserved.
  3.  
  4. //--------------------------------------------------------------------------------------------------
  5.  
  6. #ifndef __STDIO__
  7. #include <StdIo.h>
  8. #endif
  9.  
  10. #ifndef __UGEOMETRY__
  11. #include <UGeometry.h>
  12. #endif
  13.  
  14. #ifndef __ULIST__
  15. #include <UList.h>
  16. #endif
  17.  
  18. #ifndef __ALIASES__
  19. #include <Aliases.h>
  20. #endif
  21.  
  22. #ifndef __UFILE__
  23. #include <UFile.h>
  24. #endif
  25.  
  26. #ifndef __EDITIONS__
  27. #include <Editions.h>
  28. #endif
  29.  
  30. #ifndef __DIALOGS__
  31. #include <Dialogs.h>
  32. #endif
  33.  
  34. #ifndef __UAPPLICATION__
  35. #include <UApplication.h>
  36. #endif
  37.  
  38. #ifndef __UDOCUMENT__
  39. #include <UDocument.h>
  40. #endif
  41.  
  42. #ifndef __USCROLLER__
  43. #include <UScroller.h>
  44. #endif
  45.  
  46. #ifndef __SCRAP__
  47. #include <Scrap.h>
  48. #endif
  49.  
  50. #ifndef __UCLIPBOARDMGR__
  51. #include <UClipboardMgr.h>
  52. #endif
  53.  
  54. #ifndef __UPRINTHANDLER__
  55. #include <UPrintHandler.h>
  56. #endif
  57.  
  58. #ifndef __UFAILURE__
  59. #include <UFailure.h>
  60. #endif
  61.  
  62. #ifndef __UMACAPPUTILITIES__
  63. #include <UMacAppUtilities.h>
  64. #endif
  65.  
  66. #ifndef __UPATCH__
  67. #include <UPatch.h>
  68. #endif
  69.  
  70. #ifndef __UMEMORY__
  71. #include <UMemory.h>
  72. #endif
  73.  
  74. #ifndef __UMACAPPGLOBALS__
  75. #include <UMacAppGlobals.h>
  76. #endif
  77.  
  78. #ifndef __UERRORMGR__
  79. #include <UErrorMgr.h>
  80. #endif
  81.  
  82. #ifndef __MENUS__
  83. #include <Menus.h>
  84. #endif
  85.  
  86. #ifndef __UMENUMGR__
  87. #include <UMenuMgr.h>
  88. #endif
  89.  
  90. #ifndef __ERRORS__
  91. #include <Errors.h>
  92. #endif
  93.  
  94. #ifndef __TOOLUTILS__
  95. #include <ToolUtils.h>
  96. #endif
  97.  
  98. #ifndef __PACKAGES__
  99. #include <Packages.h>
  100. #endif
  101.  
  102. #ifndef __FONTS__
  103. #include <Fonts.h>
  104. #endif
  105.  
  106. #ifndef __SCRIPT__
  107. #include <Script.h>
  108. #endif
  109.  
  110. #ifndef __GESTALTEQU__
  111. #include <GestaltEqu.h>
  112. #endif
  113.  
  114. #ifndef __UTECOMMANDS__
  115. #include <UTECommands.h>
  116. #endif
  117.  
  118. #include "UTEView.h"
  119.  
  120. //--------------------------------------------------------------------------------------------------
  121. ProcPtr gDefClikLoopProc;            //  Standard TextEdit click loop routine
  122.  
  123. /*  The following are considered private, but appear in the interface in case you need to
  124.   override a method that uses one of these.  */
  125. TTEView* pCurrTEView;
  126.  
  127. #if qDebug
  128. Boolean pTEIntenseDebugging;        //  For the benefit of ClikLoopForTTEView only
  129. #endif
  130.  
  131. //--------------------------------------------------------------------------------------------------
  132. #pragma segment TEInit
  133.  
  134. pascal void InitUTEView(void)
  135. {
  136.     if (qTemplateViews)
  137.     {
  138.         // So linker doesn't strip TTEView class 
  139.         DontDeadStrip(TTEView);
  140.  
  141.         RegisterStdType("TTEView", kStdTEView);
  142.     }
  143.  
  144.     gUTEViewInitialized = TRUE;
  145. }
  146.  
  147. //--------------------------------------------------------------------------------------------------
  148. #pragma segment TEDebug
  149.  
  150. const short kMaxIndex = 2047;
  151. typedef char x[kMaxIndex];
  152. typedef x* XPtr;
  153. typedef XPtr* XHandle;
  154.  
  155.  
  156. void WriteChar(short index,
  157.                       Handle hText)
  158. {
  159.     if (index <= kMaxIndex)
  160.         fprintf(stderr, "[%1d:%1d]", index, *((XHandle)hText)[index]);
  161. }
  162.  
  163. //--------------------------------------------------------------------------------------------------
  164. #pragma segment TEDebug
  165.  
  166. pascal void DumpTERecord(TEHandle aTEH)
  167. {
  168.  
  169.     const short kMaxCharsToPrint = 100;
  170.  
  171.     short size;
  172.  
  173.     fprintf(stderr, "TE -- dest rect: ");
  174.     WriteRect((**aTEH).destRect);
  175.     fprintf(stderr, "\n");
  176.  
  177.     size = (**aTEH).teLength;
  178.     fprintf(stderr, "Line ht: %1d", (**aTEH).lineHeight);
  179.     fprintf(stderr, "; teLength: %1d", size);
  180.     fprintf(stderr, "; hText length: %1d", GetHandleSize((**aTEH).hText));
  181.     fprintf(stderr, "; lines: %1d", (**aTEH).nLines);
  182.     fprintf(stderr, "\n");
  183.  
  184.     if (gIntenseDebugging)
  185.     {
  186.         Handle hText = (**aTEH).hText;
  187.  
  188.         fprintf(stderr, "Chars: ");
  189.         for (short i = 0; i <= Min(kMaxCharsToPrint, Min(2047, size - 1)); ++i)
  190.         {
  191.             WriteChar(i, hText);
  192.             if (i % 10 == 9)
  193.                 fprintf(stderr, "\n");
  194.         }
  195.         fprintf(stderr, "\n");
  196.  
  197.         fprintf(stderr, "InPort vis bbox: ");
  198.         WriteRect((**((**aTEH).inPort->visRgn)).rgnBBox);
  199.         fprintf(stderr, "; clip bbox: ");
  200.         WriteRect((**((**aTEH).inPort->clipRgn)).rgnBBox);
  201.         fprintf(stderr, "\n");
  202.  
  203.         if ((**aTEH).inPort != qd.thePort)
  204.         {
  205.             fprintf(stderr, "thePort vis bbox: ");
  206.             WriteRect((**(qd.thePort->visRgn)).rgnBBox);
  207.             fprintf(stderr, "; clip bbox: ");
  208.             WriteRect((**(qd.thePort->clipRgn)).rgnBBox);
  209.             fprintf(stderr, "\n");
  210.         }
  211.     }
  212.  
  213. }
  214.  
  215. //--------------------------------------------------------------------------------------------------
  216. #pragma segment TERes
  217.  
  218. pascal void SetSelect(short theStart,
  219.                       short theEnd,
  220.                       TEHandle hTE)
  221. {
  222.     (**hTE).selStart = theStart;
  223.     (**hTE).selEnd = theEnd;
  224. }
  225.  
  226. //--------------------------------------------------------------------------------------------------
  227. #pragma segment TENonRes
  228.  
  229. pascal Boolean ClickLoopForTTEView(void)
  230. {
  231.     if (pCurrTEView != NULL)
  232.         return pCurrTEView->ClikLoop();
  233.     else
  234.         return TRUE;
  235. }
  236.  
  237. //--------------------------------------------------------------------------------------------------
  238. #pragma segment TEOpen
  239.  
  240. pascal void TTEView::Initialize(void)            // override 
  241. {
  242.     inherited::Initialize();
  243. #if qDebug
  244.     if (!gUTEViewInitialized)
  245.     {
  246.         ProgramBreak("InitUTEView must be called before creating a TE View.");
  247.         Failure(noErr, 0);
  248.     }
  249. #endif
  250.  
  251. #if qDebug
  252.     pTEIntenseDebugging = FALSE;
  253. #endif
  254.  
  255.     fHTE = NULL;
  256.     fText = NULL;
  257.     fSavedTEHandle = NULL;
  258.     fInset = gZeroVRect;
  259.     fKeyCmdNumber = cTyping;
  260.     fMaxChars = kUnlimited;
  261.     fLastHeight = 0;
  262.     fLastWidth = 0;
  263.     fTypingCommand = NULL;
  264.     fTextStyle = gSystemStyle;
  265.     fJustification = teFlushDefault;
  266.  
  267.     fAcceptsChanges = TRUE;                        /* Stuff to FALSE if you don't want to allow
  268.                                                   Cut, Paste, or Typing */
  269.     //!!! put these in the template after 2.0 !!!
  270.     // fControlChars = [chLeft, chRight, chUp, chDown, chBackspace, chReturn];
  271.     fControlChars = ASSETELEM(chLeft) | ASSETELEM(chRight) |
  272.                     ASSETELEM(chUp) | ASSETELEM(chDown) |
  273.                     ASSETELEM(chBackspace) | ASSETELEM(chReturn);
  274.  
  275.     fMinAhead = kMinAhead;
  276.  
  277.     fStyleType = kWithStyle;
  278.     fAutoWrap = TRUE;
  279.     fFreeText = TRUE;
  280.     fSpecsChanged = FALSE;
  281.  
  282.     fLastPageBreak = 0;
  283.     fLastLine = 0;
  284.  
  285.     fSelAnchor = 0;
  286.     fUpDown = FALSE;
  287.  
  288.     fCursorID = iBeamCursor;
  289.  
  290. }
  291.  
  292. //--------------------------------------------------------------------------------------------------
  293. #pragma segment TEOpen
  294.  
  295. pascal void TTEView::ITEView(TDocument* itsDocument,
  296.                              TView* itsSuperView,
  297.                              const VPoint& itsLocation,
  298.                              const VPoint& itsSize,
  299.                              SizeDeterminer itsHDeterminer,
  300.                              SizeDeterminer itsVDeterminer,
  301.                              const VRect& itsInset,
  302.                              const TextStyle& itsTextStyle,
  303.                              short itsJustification,
  304.                              Boolean itsStyleType,
  305.                              Boolean itsAutoWrap)
  306.  
  307. {
  308.     this->IView(itsDocument, itsSuperView, itsLocation, itsSize, itsHDeterminer, itsVDeterminer);
  309.  
  310.     fInset = itsInset;
  311.     fTextStyle = itsTextStyle;
  312.     fJustification = itsJustification;
  313.     fStyleType = itsStyleType;
  314.     fAutoWrap = itsAutoWrap;
  315.  
  316.     this->MakeTERecord();
  317.  
  318.     fSelAnchor = (*fHTE)->selStart;
  319.     SetClikLoop(&ClickLoopForTTEView, fHTE);    // (*fHTE)->clikLoop = &ClickLoopForTTEView; 
  320.     // ??? Things don't work well if fText is non-NULL.  Is this the way to solve it? 
  321.     fText = (*fHTE)->hText;
  322.  
  323.     this->SetIdleFreq(0);                        // Idle ASAP 
  324.     
  325.     this->AddAdorner(gSelectionAdorner, kViewAdornPriority, FALSE); // Wants DoHighlightSelection called
  326. }
  327.  
  328. //--------------------------------------------------------------------------------------------------
  329. #pragma segment TEOpen
  330.  
  331. pascal void TTEView::IRes(TDocument* itsDocument,
  332.                           TView* itsSuperView,
  333.                           Ptr& itsParams)        // override 
  334. {
  335.     TextStyle aTextStyle;
  336.     VRect vr;
  337.  
  338.     inherited::IRes(itsDocument, itsSuperView, itsParams);
  339.  
  340.     TEViewTemplate& templateData = *((TEViewTemplate *) itsParams);
  341.  
  342.     {
  343.         fTypingCommand = NULL;
  344.         fLastHeight = 0;
  345.         fLastWidth = 0;
  346.         fSpecsChanged = FALSE;
  347.  
  348.         vr = templateData.itsInset;
  349.         fInset = vr;
  350.         fKeyCmdNumber = templateData.itsKeyCmdNumber;
  351.         fMaxChars = templateData.itsMaxChars;
  352.         SetTextStyle(aTextStyle, GetFontNum(templateData.itsFontName), templateData.itsTextFace, templateData.itsTextSize, templateData.itsTextColor);
  353.         fTextStyle = aTextStyle;
  354.         fJustification = templateData.itsJustification;
  355.         fAcceptsChanges = templateData.itsAcceptsChanges;
  356.         fStyleType = templateData.itsStyleType;
  357.         fAutoWrap = templateData.itsAutoWrap;
  358.         fFreeText = templateData.itsFreesText;
  359.  
  360.         this->MakeTERecord();
  361.  
  362.         fSelAnchor = (**fHTE).selStart;
  363.         SetClikLoop(&ClickLoopForTTEView, fHTE);// (*fHTE)->clikLoop = &ClickLoopForTTEView; 
  364.         fText = (**fHTE).hText;
  365.  
  366.         this->SetIdleFreq(0);                    // Idle ASAP 
  367.     }
  368.  
  369.     OffsetPtrWStr(itsParams, sizeof(TEViewTemplate));
  370.  
  371.     this->AddAdorner(gSelectionAdorner, kViewAdornPriority, FALSE); // Wants DoHighlightSelection called
  372. }
  373.  
  374. //--------------------------------------------------------------------------------------------------
  375. #pragma segment TERes
  376.  
  377. pascal TObject* TTEView::Clone(void)            // override 
  378. {
  379.     TTEView * aClonedTTEView;
  380.     TEStyleHandle inputStyles;
  381.     TEStyleHandle theStyles;
  382.     TEStyleHandle oldStyles;
  383.     STHandle inputElements;
  384.     STHandle theElements;
  385.     STHandle oldElements;
  386.     LHHandle theLineHeights;
  387.     LHHandle oldLineHeights;
  388.     NullStHandle theNullStyles;
  389.     Handle theText;
  390.  
  391.     aClonedTTEView = (TTEView *)(inherited::Clone());
  392.  
  393.     if (this->fHTE != NULL)
  394.     {
  395.         HLock((Handle)(this->fHTE));
  396.         if (this->fStyleType == kWithStyle)
  397.             aClonedTTEView->fHTE = TEStylNew((**(this->fHTE)).destRect, (**(this->fHTE)).viewRect);
  398.         else
  399.             aClonedTTEView->fHTE = TENew((**(this->fHTE)).destRect, (**(this->fHTE)).viewRect);
  400.  
  401.         SetClikLoop(&ClickLoopForTTEView, aClonedTTEView->fHTE);
  402.  
  403.         // Clone the styles record since clone or stuffstyles doesn't do it for us 
  404.         if (this->fStyleType == kWithStyle)
  405.         {
  406.             this->ExtractStyles(inputStyles, inputElements);
  407.             oldStyles = GetStylHandle(aClonedTTEView->fHTE);
  408.  
  409.             theNullStyles = (**oldStyles).nullStyle;
  410.             oldElements = (**oldStyles).styleTab;
  411.             oldLineHeights = (**oldStyles).lhTab;
  412.             oldElements = (STHandle)(DisposeIfHandle((Handle)oldElements));
  413.             oldLineHeights = (LHHandle)(DisposeIfHandle((Handle)oldLineHeights));
  414.  
  415.             theStyles = inputStyles;
  416.             FailOSErr(HandToHand((Handle&)theStyles));
  417.  
  418.             theElements = inputElements;
  419.             FailOSErr(HandToHand((Handle&)theElements));
  420.  
  421.             theLineHeights = (**inputStyles).lhTab;
  422.             FailOSErr(HandToHand((Handle&)theLineHeights));
  423.  
  424.             (**theStyles).nullStyle = theNullStyles;// Replace null style handle 
  425.             (**theStyles).lhTab = theLineHeights;// Replace line heights table handle 
  426.             (**theStyles).styleTab = theElements;// Replace STElements handle 
  427.  
  428.             // NOTE!! SetStylHandle will dispose of oldStyles for us! 
  429.             SetStylHandle(theStyles, aClonedTTEView->fHTE);
  430.         }
  431.  
  432.         aClonedTTEView->fSavedTEHandle = (**(aClonedTTEView->fHTE)).hText;// Save existing handle 
  433.         theText = this->fText;
  434.         FailOSErr(HandToHand((Handle&)theText));
  435.         (**(aClonedTTEView->fHTE)).hText = theText;// Install new handle 
  436.         aClonedTTEView->fText = theText;        // Make a local copy, too 
  437.  
  438.         //!!! Note SIze->short cast
  439.         (**(aClonedTTEView->fHTE)).teLength = (short)GetHandleSize((**(aClonedTTEView->fHTE)).hText);// Tell TE how long we are 
  440.  
  441.         if (aClonedTTEView->fStyleType == kWithStyle)    // Fix for styled TE. Yuk. 
  442.             (**theStyles).runs[0].startChar = (**(aClonedTTEView->fHTE)).teLength++;
  443.  
  444.         HUnlock((Handle)(this->fHTE));
  445.     }
  446.  
  447.     aClonedTTEView->RecalcText();
  448.  
  449.     aClonedTTEView->fTypingCommand = NULL;
  450.  
  451.     return aClonedTTEView;
  452. }
  453.  
  454. //--------------------------------------------------------------------------------------------------
  455. #pragma segment MAWriteRes
  456.  
  457. pascal void TTEView::WRes(ViewRsrcHandle theResource,
  458.                           Ptr& itsParams)        // override 
  459. {
  460.     Str255 theFont;
  461.     VRect vr;
  462.     Rect r;
  463.  
  464.     inherited::WRes(theResource, itsParams);
  465.  
  466.     GetFontName(fTextStyle.tsFont, theFont);
  467.  
  468.     TEViewTemplate& templateData = *((TEViewTemplate *) ExpandPtrWStr((Handle)theResource, itsParams, sizeof(TEViewTemplate), theFont.Length()));
  469.  
  470.     templateData.itsStyleType = fStyleType;
  471.     templateData.itsAutoWrap = fAutoWrap;
  472.     templateData.itsAcceptsChanges = fAcceptsChanges;
  473.     templateData.itsFreesText = fFreeText;
  474.     templateData.itsKeyCmdNumber = (short)fKeyCmdNumber;//!!! Note long->short cast
  475.     templateData.itsMaxChars = fMaxChars;
  476.     vr = fInset;
  477.     r = vr;
  478.     templateData.itsInset = r;
  479.     templateData.itsJustification = fJustification;
  480.     templateData.itsTextFace = fTextStyle.tsFace;
  481.     templateData.itsTextSize = fTextStyle.tsSize;
  482.     templateData.itsTextColor = fTextStyle.tsColor;
  483.  
  484.     // itsFontName = theFont; 
  485.     CopyStr255(theFont, PRStr(templateData.itsFontName));
  486. }
  487.  
  488. //--------------------------------------------------------------------------------------------------
  489. #pragma segment MAWriteRes
  490.  
  491. pascal void TTEView::WriteRes(ViewRsrcHandle theResource,
  492.                               Ptr& itsParams)    // override 
  493. {
  494.     gWResSignature = 'tevw';
  495.     gWResType = "TTEView";
  496.     this->WRes(theResource, itsParams);
  497. }
  498.  
  499. //--------------------------------------------------------------------------------------------------
  500. #pragma segment TEClose
  501.  
  502. pascal void TTEView::Free(void)                    // override 
  503. {
  504.     if (fHTE != NULL)
  505.     {
  506.         if (fSavedTEHandle != NULL)
  507.         {
  508.             // Worry about fText separately. Put back 
  509.             (**fHTE).hText = fSavedTEHandle;    // …the handle which TE allocated 
  510.             (**fHTE).teLength =                    // This is here because it only makes 
  511.                                (short)GetHandleSize((**fHTE).hText);//!!! Note Size->short cast
  512.             if (fFreeText)                        // …sense if fSavedTEHandle is not NULL. 
  513.                 fText = DisposeIfHandle(fText);
  514.             fText = NULL;                        // Always drop my reference 
  515.         }
  516.         TEDispose(fHTE);
  517.         fHTE = NULL;
  518.  
  519.         fSavedTEHandle = NULL;
  520.     }
  521.  
  522.     inherited::Free();
  523. }
  524.  
  525. //--------------------------------------------------------------------------------------------------
  526. #pragma segment TERes
  527. pascal void TTEView::Activate(Boolean entering)    // Override 
  528. {
  529.     inherited::Activate(entering);
  530.  
  531.     if (entering)
  532.     {
  533.         if (fHTE)
  534.         {
  535.             if (fIdleFreq == kMaxIdleTime)
  536.                 this->SetIdleFreq(0);                            // Idle ASAP 
  537.             SetKeyScript(Font2Script(fTextStyle.tsFont));
  538.             this->SetActive(TRUE);
  539.             pCurrTEView = this;                            // So the global clikLoop routine can forward 
  540.         }
  541.     }
  542.     else
  543.     {
  544.         this->SetActive(FALSE);
  545.         this->DoneTyping();
  546.         fSpecsChanged = TRUE;
  547.     }
  548. }
  549.  
  550. //--------------------------------------------------------------------------------------------------
  551. #pragma segment TERes
  552.  
  553. pascal void TTEView::DoHighlightSelection(HLState fromHL,
  554.                                         HLState toHL)    // Override
  555. {        
  556.     if (fHTE)
  557.     {
  558.         /*
  559.         if ((toHL == hlOn) && (TEFeatureFlag(teFOutlineHilite, TEBitTest, fHTE) == TEBitSet))
  560.             TEFeatureFlag(teFOutlineHilite, TEBitSet, fHTE);
  561.             
  562.         if ((toHL == hlDim) || (fromHL == hlDim))
  563.             TEFeatureFlag(teFOutlineHilite, TEBitSet, fHTE);
  564.         else 
  565.             TEFeatureFlag(teFOutlineHilite, TEBitClear, fHTE);
  566.         */
  567.             
  568.         /*
  569.         switch (fromHL + toHL)
  570.         {
  571.             // case hlOffOn:
  572.             case hlOnOff:
  573.                 TEFeatureFlag(teFOutlineHilite, TEBitClear, fHTE);
  574.                 break;
  575.     
  576.             // case hlOffDim:
  577.             case hlDimOff:
  578.             // case hlDimOn:
  579.             case hlOnDim:
  580.                 TEFeatureFlag(teFOutlineHilite, TEBitSet, fHTE);
  581.                 break;
  582.         }
  583.         */
  584.     }
  585. }
  586.  
  587. //--------------------------------------------------------------------------------------------------
  588. #pragma segment TERes
  589.  
  590. pascal void TTEView::BecameWindowTarget(void)            // Override 
  591. {
  592.     if (fHTE)
  593.     {
  594.         if (fIdleFreq == kMaxIdleTime)
  595.             this->SetIdleFreq(0);                            // Idle ASAP 
  596.         SetKeyScript(Font2Script(fTextStyle.tsFont));
  597.         this->DoHighlightSelection(hlDim,hlOn);
  598.         this->SetActive(TRUE);
  599.         pCurrTEView = this;                            // So the global clikLoop routine can forward 
  600.     }
  601.  
  602.     inherited::BecameWindowTarget();
  603. }
  604.  
  605. //--------------------------------------------------------------------------------------------------
  606. #pragma segment TERes
  607.  
  608. pascal void TTEView::BecameApplicationTarget(void)            // Override 
  609. {
  610. /*    if (fHTE)
  611.     {
  612.         if (fIdleFreq == kMaxIdleTime)
  613.             this->SetIdleFreq(0);                            // Idle ASAP 
  614.         SetKeyScript(Font2Script(fTextStyle.tsFont));
  615.     //    this->DoHighlightSelection(hlDim,hlOn);
  616.         this->SetActive(TRUE);
  617.         pCurrTEView = this;                            // So the global clikLoop routine can forward 
  618.     }
  619. */
  620.     inherited::BecameApplicationTarget();
  621. }
  622.  
  623. //--------------------------------------------------------------------------------------------------
  624. #pragma segment TENonRes
  625.  
  626. pascal Boolean TTEView::ClikLoop()
  627. {
  628.     VPoint viewPt;
  629.     Rect visRect;
  630.     VPoint delta;
  631.     short lead;
  632.     short trail;
  633.     TScroller * scroller;
  634.     Point msePt;
  635.  
  636.  
  637.     if (StillDown())
  638.     {
  639.         scroller = this->GetScroller(FALSE);
  640.         if ((scroller != NULL) && scroller->Focus())
  641.         {
  642.             GetMouse(msePt);
  643.             scroller->QDToViewPt(msePt, viewPt);
  644.             scroller->AutoScroll(viewPt, delta);// find how much should scroll 
  645.             if (this->Focus())
  646.             {
  647.                 this->GetVisibleQDRect(visRect);
  648.                 for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  649.                 {
  650.                     lead = (short)(fLocation[vhs] - visRect[topLeft][vhs]);//!!! long->short cast
  651.                     trail = (short)(fLocation[vhs] + fSize[vhs] - visRect[botRight][vhs]);//!!! long->short cast
  652.  
  653.                     if (delta[vhs] < 0)
  654.                     {
  655.                         // !!!FIX the following 2 lines after MPW C compiler bug is corrected.
  656.                         long temp = Min(Max(delta[vhs], lead), 0);
  657.                         delta[vhs] = temp;
  658.                     }
  659.                     else
  660.                     {
  661.                         // !!!FIX the following 2 lines after MPW C compiler bug is corrected.
  662.                         long temp1 = Max(Min(delta[vhs], trail), 0);
  663.                         delta[vhs] = temp1;
  664.                     }
  665.                 }
  666.                 /* The intent of the above is not to do autoscrolling that would scroll
  667.                   beyond the subview boundary in any direction */
  668.  
  669.                 if (delta != gZeroVPt)
  670.                 {
  671.                     scroller->ScrollBy(delta, kRedraw);
  672.                     this->Update();                // make sure the scrolling was visible 
  673.                 }
  674.             }
  675.         }
  676.  
  677.         /* Focus may have changed, which could change lots of things, thus
  678.           requiring us, tiresomely, to take some or all of the following
  679.           restorative precautions b/c clikloop expects us to be clipped to the
  680.           destrect. */
  681.         if (this->Focus())
  682.             this->ClipFurtherTo((**fHTE).destRect, 0, 0);
  683.     }
  684.     return TRUE;                                // Still consider the mouse to be down 
  685. }
  686.  
  687. //--------------------------------------------------------------------------------------------------
  688. #pragma segment TENonRes
  689.  
  690. pascal void TTEView::AutoScrolling(Boolean doScrolling)
  691. {
  692.     if (fHTE != NULL)
  693.         TEAutoView(doScrolling, fHTE);
  694. }
  695.  
  696. //--------------------------------------------------------------------------------------------------
  697. #pragma segment TENonRes
  698.  
  699. pascal void TTEView::BeInPort(GrafPtr itsPort)    // override 
  700. {
  701.  
  702.     if (fHTE != NULL)
  703.     {
  704.         if (itsPort == NULL)
  705.             (**fHTE).inPort = gWorkPort;
  706.         else
  707.             (**fHTE).inPort = itsPort;
  708.  
  709.         if (itsPort == NULL)
  710.         {
  711.             this->DoneTyping();
  712.             fSpecsChanged = TRUE;
  713.         }
  714.     }
  715.  
  716.     inherited::BeInPort(itsPort);
  717. }
  718.  
  719. //--------------------------------------------------------------------------------------------------
  720. #pragma segment TENonRes
  721.  
  722. pascal void TTEView::BeInScroller(TScroller* itsScroller)// override 
  723. {
  724.     short vertScrollUnit;
  725.  
  726.  
  727.     if ((fHTE != NULL) && (itsScroller != NULL))
  728.     {
  729.         if ((**fHTE).lineHeight > 0)            // This works for both old && new TextEdit 
  730.             vertScrollUnit = (**fHTE).lineHeight;
  731.         else
  732.             vertScrollUnit = GetDefFontSize();    // Ask for system default size 
  733.  
  734.         itsScroller->SetScrollParameters(VPoint(vertScrollUnit, kStdScrollUnit), FALSE, TRUE);
  735.     }
  736.  
  737.     inherited::BeInScroller(itsScroller);
  738. }
  739.  
  740. //--------------------------------------------------------------------------------------------------
  741. #pragma segment TENonRes
  742.  
  743. pascal void TTEView::CalcMinSize(VPoint& minSize)// override 
  744. {
  745.     /* Note that we omit the margins here, so that if TView.ComputeExtent rounds up to a
  746.       page multiple, the margins will get tacked on after.  Also, insure we don't run off
  747.       the end of the coordinate system if there are many lines of text. */
  748.  
  749.     minSize = VPoint(Min(kMaxCoord, this->CalcRealHeight()), fSize.h - fInset.left - fInset.right);
  750.  
  751.     if ((fSizeDeterminer[hSel] == sizeVariable) &&!fStyleType &&!fAutoWrap)
  752.         minSize = VPoint(minSize.v, fLastWidth);
  753. }
  754.  
  755. //--------------------------------------------------------------------------------------------------
  756. #pragma segment TERes
  757.  
  758. pascal long TTEView::CalcRealHeight(void)
  759. {
  760.     Boolean lastIsCR;
  761.     short theMode;
  762.     long theHeight;
  763.     TextStyle theStyle;
  764.     FontInfo theFontInfo;
  765.     short theFontHeight;
  766.  
  767.  
  768.     TERec & theTERec = **fHTE;
  769.  
  770.     lastIsCR = (theTERec.teLength <= 0) || ((*(CharsHandle)(theTERec.hText))[theTERec.teLength - 1] == chReturn);
  771.  
  772.     if (fStyleType == kWithStyle)
  773.     {
  774.         theHeight = 0;
  775.         if (theTERec.nLines > 0)
  776.             theHeight = TEGetHeight(MAXINT, 0, fHTE);
  777.  
  778.         if (lastIsCR)                            // then can't use TEGetHeight so we 
  779.         {
  780.             // …have to figure it out ourselves. 
  781.             theMode = doAll;
  782.             lastIsCR = this->ContinuousStyle(MAXINT, MAXINT, theMode, theStyle);
  783.  
  784.             GetTextStyleFontInfo(theStyle, theFontInfo, theFontHeight);
  785.  
  786.             theHeight = theHeight + theFontHeight;
  787.         }
  788.     }
  789.  
  790.     else
  791.     {
  792.         theHeight = theTERec.nLines + (long)(lastIsCR);
  793.         theHeight = theHeight * theTERec.lineHeight;
  794.     }
  795.  
  796. #if qDebugMsg
  797.     if (gIntenseDebugging)
  798.         fprintf(stderr, "CalcRealHeight=%1d\n", theHeight);
  799. #endif
  800.  
  801.     return theHeight;
  802. }
  803.  
  804. //--------------------------------------------------------------------------------------------------
  805. #pragma segment TERes
  806.  
  807. pascal long TTEView::CalcRealWidth(void)
  808. {
  809.     short fromChar;
  810.     short toChar;
  811.     short aWidth;
  812.     TextStyle theStyle;
  813.     SignedByte savedState;
  814.  
  815.  
  816.     aWidth = 0;
  817.     /* !!! it would be nice to compute this for styled TE but TEGetPoint only returns the bottom
  818.       left of the character box so it can't be used to find the width including last character
  819.       in a line.    And since some characters can change width based on context we can't just
  820.       measure the last character and add it in.  Maybe we can makeup an formula based on
  821.       style runs or something eventually. */
  822.     if (!fStyleType)
  823.     {
  824.         if (this->Focus())
  825.         {
  826.             theStyle = fTextStyle;
  827.             SetPortTextStyle(theStyle);
  828.  
  829.             aWidth = 0;
  830.             fromChar = (**fHTE).lineStarts[0];
  831.  
  832.             savedState = LockHandleHigh((Handle)(**fHTE).hText);
  833.  
  834.             for (short index = 1; index <= (**fHTE).nLines; ++index)
  835.             {
  836.                 toChar = (**fHTE).lineStarts[index] - 1;
  837.                 aWidth = (short)Max(aWidth, TextWidth(*((**fHTE).hText), fromChar, (toChar - fromChar) + 1));//!!! long->short cast
  838.                 fromChar = toChar + 1;
  839.             }
  840.  
  841.             HSetState((Handle)(**fHTE).hText, savedState);
  842.  
  843.             return aWidth;
  844.         }
  845.     }
  846.     else if (qDebug)
  847.         ProgramBreak("IN TTEView.CalcRealWidth: called for a styled TE Record");
  848.     return aWidth;
  849. }
  850.  
  851. //--------------------------------------------------------------------------------------------------
  852. #pragma segment TENonRes
  853.  
  854. pascal void TTEView::ChangeWrap(Boolean newAutoWrap,
  855.                                 Boolean redraw)
  856. {
  857.     fAutoWrap = newAutoWrap;
  858.     if (newAutoWrap)
  859.         (**fHTE).crOnly = 0;
  860.     else
  861.         (**fHTE).crOnly = -1;
  862.     if (redraw)
  863.     {
  864.         this->RecalcText();
  865.         this->SynchView(kRedraw);
  866.     }
  867. }
  868.  
  869. //--------------------------------------------------------------------------------------------------
  870. #pragma segment TENonRes
  871.  
  872. pascal Boolean NeedAdjust(SizeDeterminer aSizeDeterminer)
  873. {
  874.     return !((aSizeDeterminer == sizeFixed) || (aSizeDeterminer == sizeSuperView) || (aSizeDeterminer == sizeRelSuperView));
  875. }
  876.  
  877. pascal void TTEView::ComputeSize(VPoint& newSize)// override 
  878.  
  879. {
  880.     inherited::ComputeSize(newSize);
  881.  
  882.     if (NeedAdjust(fSizeDeterminer[hSel]))        // If necessary, tack on the margins 
  883.         newSize.h = Min(kMaxCoord, newSize.h + fInset.left + fInset.right);
  884.     if (NeedAdjust(fSizeDeterminer[vSel]))
  885.         newSize.v = Min(kMaxCoord, newSize.v + fInset.top + fInset.bottom);
  886. }
  887.  
  888. //--------------------------------------------------------------------------------------------------
  889. #pragma segment TERes
  890.  
  891. pascal void TTEView::CalcSelLoc(VRect& selectionRect)
  892. {
  893.  
  894.     const short kSlopToAllow = 36;
  895.  
  896.     CharsHandle handleToText;
  897.     short startOfSelection;
  898.     short endOfSelection;
  899.     short charCount;
  900.     short lineHeight;
  901.     short fontAscent;
  902.     TextStyle theStyle;
  903.     Boolean selectionIsTheLastReturn;
  904.     short theMode;
  905.     FontInfo theFontInfo;
  906.     short theFontHeight;
  907.     VPoint temp;
  908.     VPoint temp1;
  909.  
  910.     {
  911.         TERec& theTERec = **fHTE;
  912.     
  913.         charCount = theTERec.teLength;
  914.         startOfSelection = theTERec.selStart;
  915.         endOfSelection = theTERec.selEnd;
  916.         handleToText = (CharsHandle)(theTERec.hText);
  917.     
  918.         if ((theTERec.selEnd - theTERec.selStart == 0) && (fIdleFreq == kMaxIdleTime))
  919.             this->SetIdleFreq(0);                    // Idle ASAP 
  920.     }
  921.  
  922.     selectionIsTheLastReturn = (startOfSelection == charCount) && (charCount > 0) && ((*handleToText)[charCount - 1] == chReturn);
  923.  
  924.     // !!!FIX the following 2 lines after MPW C compiler bug is corrected.
  925.     this->OffsetToPt(startOfSelection, temp);
  926.     selectionRect[topLeft] = temp;
  927.  
  928.     // OffsetToPt returns the baseline point.  Correct for the lineheight 
  929.     TEGetStyle(startOfSelection, theStyle, lineHeight, fontAscent, fHTE);
  930.     selectionRect.top = selectionRect.top - lineHeight;
  931.  
  932.     // !!!FIX the following 2 lines after MPW C compiler bug is corrected.
  933.     this->OffsetToPt(endOfSelection, temp1);
  934.     selectionRect[botRight] = temp1;/* Darn! wish we could know where the
  935.                                                   point to the bottom right of an offset
  936.                                                   is!!! This way we can't ever return the
  937.                                                   "real" rectangle that encloses the
  938.                                                   selection. */
  939.  
  940.     if (selectionIsTheLastReturn)
  941.     {
  942.         theMode = doAll;
  943.  
  944.         // Get the style so we know how tall to make the selection when its just the last return 
  945.         this->ContinuousStyle(MAXINT, MAXINT, theMode, theStyle);
  946.  
  947.         GetTextStyleFontInfo(theStyle, theFontInfo, theFontHeight);
  948.  
  949.         selectionRect.top = selectionRect.bottom;
  950.         selectionRect.bottom += theFontHeight;
  951.     }
  952.     else
  953.     {
  954.         /* Correct errors by CalcSelLoc.  If there is no selection then the "selection" consists of
  955.           the bits enclosed by the insertion bar. */
  956.         if (((**fHTE).selEnd - (**fHTE).selStart) == 0)
  957.             selectionRect.left = selectionRect.right - 1;
  958.  
  959.     }
  960. }
  961.  
  962. //--------------------------------------------------------------------------------------------------
  963. #pragma segment TERes
  964.  
  965. pascal Boolean TTEView::ContinuousStyle(short firstChar,
  966.                                         short lastChar,
  967.                                         short& mode,
  968.                                         TextStyle& aStyle)
  969. {
  970.     short oldSelStart;
  971.     short oldSelEnd;
  972.     Boolean result;
  973.  
  974.  
  975.     oldSelStart = (**fHTE).selStart;
  976.     oldSelEnd = (**fHTE).selEnd;
  977.  
  978.     SetSelect(firstChar, lastChar, fHTE);        // Use SetSelect so this is invisible 
  979.     result = TEContinuousStyle(mode, aStyle, fHTE);
  980.     SetSelect(oldSelStart, oldSelEnd, fHTE);
  981.     return result;
  982. }
  983.  
  984. //--------------------------------------------------------------------------------------------------
  985. #pragma segment TERes
  986.  
  987. pascal Boolean TTEView::ContainsClipType(ResType aType)// override 
  988. {
  989.     return (aType == 'TEXT');
  990. }
  991.  
  992. //--------------------------------------------------------------------------------------------------
  993. // Put in resident segment since this gets called while typing 
  994. #pragma segment TERes
  995.  
  996. pascal VCoordinate TTEView::DoBreakFollowing(VHSelect vhs,
  997.                                              VCoordinate prevBreak,
  998.                                              Boolean& automatic)// override 
  999. {
  1000.     VHSelect orthoVhs;
  1001.     short possibleLoc;
  1002.     TEStyleHandle theStyles;
  1003.     LHHandle lhTab;
  1004.     short height;
  1005.     short lineHeight;
  1006.     short lineNo;
  1007.  
  1008.     orthoVhs = gOrthogonal[vhs];
  1009.     automatic = TRUE;
  1010.  
  1011.     possibleLoc = (short)Min(kMaxCoord, prevBreak + fPrintHandler->fViewPerPage[orthoVhs]); //!!! long->short
  1012.  
  1013.     /* We want to get rid of the on-screen margin represented by fMargin when printing, so
  1014.       adjust things so that the portion of the view occupied by the screen margin doesn't
  1015.       get printed. */
  1016.     if (prevBreak == 0)
  1017.         possibleLoc += (short)fInset[topLeft][orthoVhs]; //!!! long->short
  1018.  
  1019.     if ((fStyleType == kWithStyle) && (vhs == hSel))
  1020.     {
  1021.         if (fLastPageBreak == prevBreak)
  1022.         {
  1023.             height = fLastPageBreak;
  1024.             lineNo = fLastLine;
  1025.         }
  1026.         else
  1027.         {
  1028.             height = (short)fInset[topLeft][orthoVhs]; //!!! VCoordinate->short
  1029.             lineNo = 0;
  1030.         }
  1031.  
  1032.         theStyles = GetStylHandle(fHTE);
  1033.         lhTab = (**theStyles).lhTab;
  1034.  
  1035.         while (lineNo < (**fHTE).nLines)
  1036.         {
  1037.             lineHeight = (*lhTab)[lineNo].lhHeight;
  1038.             if (height + lineHeight <= possibleLoc)
  1039.                 height += lineHeight;
  1040.             else
  1041.                 break;
  1042.             ++lineNo;
  1043.         }
  1044.         if (lineNo >= (**fHTE).nLines)
  1045.             possibleLoc = (short)Max(possibleLoc, height); //!!! long->short
  1046.         else
  1047.             possibleLoc = height;
  1048.         fLastPageBreak = possibleLoc;
  1049.         fLastLine = lineNo;
  1050.     }
  1051.  
  1052.     if ((possibleLoc + fInset[topLeft][orthoVhs]) >= fSize[orthoVhs])
  1053.         return fSize[orthoVhs];
  1054.     else
  1055.         return possibleLoc;
  1056. }
  1057.  
  1058. //--------------------------------------------------------------------------------------------------
  1059. #pragma segment TENonRes
  1060.  
  1061. pascal void TTEView::DoCalcViewPerPage(VPoint& viewPerPage)// override 
  1062. {
  1063.  
  1064.     inherited::DoCalcViewPerPage(viewPerPage);    // Get max amount allowed given margins 
  1065.  
  1066. #if qDebugMsg
  1067.     if (gDebugPrinting)
  1068.     {
  1069.         fprintf(stderr, "TTEView: incoming generic viewPerPage:");
  1070.         WriteVPt(viewPerPage);
  1071.         fprintf(stderr, "\n");
  1072.     }
  1073. #endif
  1074.  
  1075.     if ((fStyleType != kWithStyle) && (fHTE != NULL))// Adjust for integral # of lines per page 
  1076.         viewPerPage.v = (**fHTE).lineHeight * (viewPerPage.v / (**fHTE).lineHeight);
  1077.  
  1078. #if qDebug
  1079.     if (gDebugPrinting)
  1080.     {
  1081.         fprintf(stderr, "TTEView: computed viewPerPage:");
  1082.         WriteVPt(viewPerPage);
  1083.         fprintf(stderr, "\n");
  1084.     }
  1085. #endif
  1086.  
  1087. }
  1088.  
  1089. //--------------------------------------------------------------------------------------------------
  1090. #pragma segment TERes
  1091.  
  1092. pascal Boolean TTEView::DoIdle(IdlePhase phase)    // override 
  1093. {
  1094.     if (phase == idleContinue)
  1095.         if ((fHTE != NULL) && ((**fHTE).selEnd - (**fHTE).selStart == 0) && this->IsEnabled())
  1096.         {
  1097.             if (fAcceptsChanges && this->IsDrawable())
  1098.                 TEIdle(fHTE);
  1099.             this->SetIdleFreq(Max(GetCaretTime() / 2, 1));/* Reset idle frequency in case user changed
  1100.                                                   it*/
  1101.         }
  1102.         else
  1103.             this->SetIdleFreq(kMaxIdleTime);            // No need to bother anyone. 
  1104.     return FALSE;                                // Didn't free myself 
  1105. }
  1106.  
  1107. //--------------------------------------------------------------------------------------------------
  1108. #pragma segment TERes
  1109.  
  1110. pascal void TTEView::DoKeyCommand(TToolboxEvent* event)// override 
  1111. /* The Tab character has no width in some fonts, and so can cause confusing screen feedback.
  1112.   It is filtered out by default.  If you want to include it in your text union it into fControlChars. */
  1113. {
  1114.     TTETypingCommand * aTypingCommand = NULL;
  1115.     Boolean needNewCommand = FALSE;
  1116.     Boolean handledCharacter = FALSE;
  1117.     Boolean selecting = FALSE;
  1118.     short goToPos = (**fHTE).selStart;
  1119.     short i = 0;
  1120.     short nonAnchor;
  1121.     Boolean expanding;
  1122.     short newStart;
  1123.     short newEnd;
  1124.     Boolean towardStart;
  1125.     VPoint aVPoint;
  1126.     unsigned char ch = event->fCharacter;
  1127.  
  1128.     if (this->IsEnabled())                                        // if view is not enabled then we don't take ANY keystrokes
  1129.     {
  1130.         if ((ch >= ' ') || IN(fControlChars, ASSETELEM(ch)))    // Check that the character should be accepted
  1131.         {
  1132.             if (((ch == chLeft) || (ch == chRight) || (ch == chUp) || (ch == chDown)) && this->Focus())    // check for pure movement keys 
  1133.             {
  1134.                 this->DoneTyping();                // Like mousedown, further typing == new cmd 
  1135.                 fSpecsChanged = TRUE;
  1136.                 //################
  1137.                 if ((ch != chUp) && (ch != chDown))
  1138.                     fUpDown = FALSE;
  1139.  
  1140.                 if ((ch == chLeft) || (ch == chRight))
  1141.                 {
  1142.                     towardStart = (ch == chLeft);
  1143.                     if (GetScript((short)GetEnvirons(smKeyScript), smScriptRight) != 0)//!!! long->short
  1144.                         towardStart =!towardStart;
  1145.                 }
  1146.                 else
  1147.                     towardStart = FALSE;
  1148.  
  1149.                 {
  1150.                     TERec& theTERec = **fHTE;        //Pascal: WITH (**fHTE)
  1151.  
  1152.                     if (theTERec.selStart == theTERec.selEnd)
  1153.                         fSelAnchor = theTERec.selStart;
  1154.                     if (fSelAnchor < 0)
  1155.                         if ((ch == chUp) || (towardStart))
  1156.                             fSelAnchor = theTERec.selEnd;
  1157.                         else
  1158.                             fSelAnchor = theTERec.selStart;
  1159.                     if (fSelAnchor == theTERec.selEnd)
  1160.                         nonAnchor = theTERec.selStart;
  1161.                     else
  1162.                         nonAnchor = theTERec.selEnd;
  1163.                 }
  1164.  
  1165.                 if ((ch == chUp) && (this->OffsetToLine(nonAnchor) == 0))
  1166.                 {
  1167.                     //same as Cmd-Up
  1168.                     selecting = event->fShiftKey;
  1169.                     handledCharacter = TRUE;
  1170.                     goToPos = 0;
  1171.                     fUpDown = FALSE;
  1172.                 }
  1173.                 else if ((ch == chDown) && (this->OffsetToLine(nonAnchor) == (**fHTE).nLines - 1))
  1174.                 {
  1175.                     //same as Cmd-Down
  1176.                     selecting = event->fShiftKey;
  1177.                     handledCharacter = TRUE;
  1178.                     goToPos = (**fHTE).teLength;
  1179.                     fUpDown = FALSE;
  1180.                 }
  1181.  
  1182.                 if ((!handledCharacter) && (ch >= chLeft) && (ch <= chDown))
  1183.  
  1184.                 {
  1185.                     HLock((Handle)fHTE);
  1186.  
  1187.                     selecting = event->fShiftKey;
  1188.                     handledCharacter = TRUE;
  1189.  
  1190.                     if (event->fCmdKey)                    // Actually, Cmd-Up && Cmd-Down differ from 
  1191.                     {                                    // the Human Interface Guidelines. Let me 
  1192.                         if (ch == chUp)
  1193.                             goToPos = 0;        /* know if you think this should be
  1194.                                                   modified!*/
  1195.                         else if (ch == chDown)
  1196.                             goToPos = (**fHTE).teLength;
  1197.                         else if (towardStart)
  1198.                             goToPos = this->OffsetToLineStart(nonAnchor);
  1199.                         else
  1200.                             goToPos = this->OffsetToLineEnd(nonAnchor);
  1201.                         fUpDown = FALSE;
  1202.                     }
  1203.                     else if ((ch == chUp) || (ch == chDown))
  1204.                     {
  1205.                         if (!fUpDown)
  1206.                         {
  1207.                             VPoint aVPoint;
  1208.                             
  1209.                             fUpDown = TRUE;
  1210.                             OffsetToPt(nonAnchor, aVPoint);
  1211.                             fUpDownH = (short)aVPoint.h;    //!!! VCoordinate->short
  1212.                         }
  1213.                         if ((**fHTE).lineHeight < 0)//styled text
  1214.                         {
  1215.                             i = this->OffsetToLine(nonAnchor);
  1216.                             i = (short)TEGetHeight(((long)i), ((long)i), fHTE);//!!! long->short
  1217.                         }
  1218.                         else
  1219.                             i = (**fHTE).lineHeight;
  1220.                         if (ch == chUp)
  1221.                             i = -i;
  1222.                         this->OffsetToPt(nonAnchor, aVPoint);
  1223.                         aVPoint.v += i;
  1224.                         aVPoint.h = fUpDownH;
  1225.                         goToPos = this->PtToOffset(aVPoint);
  1226.                         i = this->OffsetToLine(nonAnchor);
  1227.                         if ((ch == chUp) && (goToPos == (**fHTE).lineStarts[i]))
  1228.                             --goToPos;
  1229.                         else if ((ch == chDown) && (this->OffsetToLine(goToPos) == i + 2))
  1230.                             ++goToPos;
  1231.                     }
  1232.                     else if (event->fOptionKey    /*& ((ch == chLeft) || (ch == chRight))*/)
  1233.                     {
  1234.                         if (selecting)
  1235.                             if (towardStart)
  1236.                                 expanding = (nonAnchor <= fSelAnchor);
  1237.                             else
  1238.                                 expanding = (nonAnchor >= fSelAnchor);
  1239.                         else
  1240.                             expanding = TRUE;
  1241.                         goToPos = nonAnchor;
  1242.                         if (!expanding)
  1243.                             if (towardStart)
  1244.                             {
  1245.                                 newEnd = goToPos;
  1246.                                 while ((goToPos > fSelAnchor) && ((!WordBounds(goToPos, newStart, newEnd)) || (newEnd + 1 >= nonAnchor)))
  1247.                                     goToPos = newStart - 1;
  1248.                                 if (goToPos <= fSelAnchor)
  1249.                                 {
  1250.                                     expanding = TRUE;
  1251.                                     goToPos = fSelAnchor;
  1252.                                 }
  1253.                                 else
  1254.                                     goToPos = newEnd + 1;
  1255.                             }
  1256.                             else                //!towardStart
  1257.                                 {
  1258.                                 newStart = goToPos;
  1259.                                 while ((goToPos < fSelAnchor) && ((!WordBounds(goToPos, newStart, newEnd)) || (newStart <= nonAnchor)))
  1260.                                     goToPos = newEnd + 1;
  1261.                                 if (goToPos >= fSelAnchor)
  1262.                                 {
  1263.                                     expanding = TRUE;
  1264.                                     goToPos = fSelAnchor;
  1265.                                 }
  1266.                             }
  1267.                         if (expanding)
  1268.                             if (towardStart)
  1269.                             {
  1270.                                 i = goToPos;
  1271.                                 newStart = goToPos;
  1272.                                 while ((goToPos > 0) && ((!WordBounds(goToPos, newStart, newEnd)) || (newStart >= i)))
  1273.                                     --goToPos;
  1274.                                 goToPos = (short)Min(goToPos, newStart);//!!! long->short
  1275.                             }
  1276.                             else                //!towardStart
  1277.                                 {
  1278.                                 newEnd = goToPos;
  1279.                                 i = (**fHTE).teLength - 1;
  1280.                                 while ((goToPos < i) &&!WordBounds(goToPos + 1, newStart, newEnd))
  1281.                                     ++goToPos;
  1282.                                 goToPos = (short)Max(goToPos, newEnd) + 1;//!!! long->short
  1283.                             }
  1284.                     }
  1285.                     else if (event->fShiftKey || ((**fHTE).selStart == (**fHTE).selEnd)/*& ((ch == chLeft) || (ch ==
  1286.                                                   chRight))*/)
  1287.                     {
  1288.                         if (towardStart)
  1289.                             i = -1;
  1290.                         else
  1291.                             i = +1;
  1292.                         goToPos = (short)Min(Max(nonAnchor + i, 0), (**fHTE).teLength);//!!! long->short
  1293.                     }
  1294.                     else                        /*selStart != selEnd && ((ch == chLeft) || (ch ==
  1295.                                                   chRight))*/
  1296.                         {
  1297.                         if (towardStart)
  1298.                             goToPos = (**fHTE).selStart;
  1299.                         else
  1300.                             goToPos = (**fHTE).selEnd;
  1301.                     }
  1302.  
  1303.                     HUnlock((Handle)fHTE);
  1304.  
  1305.                 }
  1306.                 //################
  1307.  
  1308.                 handledCharacter = TRUE;
  1309.                 //################
  1310.                 if (handledCharacter)
  1311.                 {
  1312.                     if (selecting)
  1313.                         this->SetSelection((short)Min(goToPos, fSelAnchor), (short)Max(goToPos, fSelAnchor), kRedraw);//!!! long->short
  1314.                     else
  1315.                         this->SetSelection(goToPos, goToPos, kRedraw);
  1316.                 }
  1317.                 else
  1318.                 {
  1319.                     TEKey(ch, fHTE);
  1320.                     if (selecting)
  1321.                         this->SetSelection((short)Min((**fHTE).selStart, fSelAnchor), (short)Max((**fHTE).selEnd, fSelAnchor), kRedraw);//!!! long->short
  1322.                     else if ((**fHTE).selStart == (**fHTE).selEnd)
  1323.                         fSelAnchor = (**fHTE).selStart;
  1324.                 }
  1325.                 this->ScrollSelectionIntoView();
  1326.                 //################
  1327.             }
  1328.             else if (fAcceptsChanges && this->Focus())
  1329.             {
  1330.                 // Check max size for text, and that we're not running out of memory 
  1331.                 if ((ch != chBackspace) && (ch != chFwdDelete) && ((**fHTE).selStart == (**fHTE).selEnd))
  1332.                     if (((fMaxChars - GetHandleSize(fText)) < 1) || MemSpaceIsLow())
  1333.                     {
  1334.                         StdAlert(phTooManyChars);
  1335.                         //                        exit(DoKeyCommand);             // Flush further keystrokes 
  1336.                         return;
  1337.                     }
  1338.  
  1339.                     // Pass the character to the typing command, creating a new one if necessary 
  1340.  
  1341.                 needNewCommand = (fTypingCommand == NULL);
  1342.                 if (!needNewCommand)
  1343.                     needNewCommand = fTypingCommand->fCompleted;
  1344.  
  1345.                 if (needNewCommand)
  1346.                 {
  1347.                     aTypingCommand = this->DoMakeTypingCommand(ch);
  1348.                     fTypingCommand = aTypingCommand;
  1349.                     this->PostCommand(aTypingCommand);
  1350.                 }
  1351.                 else
  1352.                 {
  1353.                     fTypingCommand->AddCharacter(ch);
  1354.                     /* Once you're typing (first character already processed) collecting subsequent
  1355.                       characters really shouldn't affect the menus unless you're keeping a character
  1356.                       count in them or something that depends on the aggregate of the characters you've
  1357.                       typed.    The TextStyle for the first character would certainly apply to subsequent
  1358.                       characters.  So, this is one ideal place to say that the event _DOES NOT_ affect
  1359.                       the menus.    If the menus are already invalid they will stay so, but if they are
  1360.                       valid then there is no need to invalidate them in the character collection process.
  1361.                       When the user terminates the addition of characters with another event, the menus
  1362.                       will be setup from that event.    If you really feel you must, then you can always
  1363.                       override, call inherited and then set event->fAffectMenus back to true. (Rhymes with
  1364.                       rue) */
  1365.                     event->fAffectsMenus = FALSE;
  1366.                 }
  1367.                 handledCharacter = TRUE;
  1368.             }
  1369.         }
  1370.         if (fIdleFreq == kMaxIdleTime)
  1371.             this->SetIdleFreq(0);                        /* Idle ASAP, since someone may somehow set
  1372.                                                   an insertion point and want it to flash.
  1373.                                                   (the idle time will be reset to match the
  1374.                                                   caret time in doidle.)*/
  1375.     }
  1376.  
  1377.     if (!handledCharacter)
  1378.         inherited::DoKeyCommand(event);
  1379. }
  1380.  
  1381. //--------------------------------------------------------------------------------------------------
  1382. #pragma segment TERes
  1383.  
  1384. pascal void TTEView::SetSelection(short NewSelStart,
  1385.                                   short NewSelEnd,
  1386.                                   Boolean redraw)
  1387. {
  1388.     if (redraw && this->Focus())
  1389.     {
  1390.         TESetSelect(Max(NewSelStart, 0), Min(NewSelEnd, (**fHTE).teLength), fHTE);
  1391.         this->SynchView(TRUE);
  1392.     }
  1393.     else
  1394.         SetSelect((short)Max(NewSelStart, 0), (short)Min(NewSelEnd, (**fHTE).teLength), fHTE);//!!! long->short
  1395.  
  1396.     if (NewSelStart == NewSelEnd)
  1397.         fSelAnchor = NewSelStart;
  1398.  
  1399.     fSpecsChanged = TRUE;
  1400. }
  1401.  
  1402. //--------------------------------------------------------------------------------------------------
  1403. #pragma segment TESelCommand
  1404.  
  1405. pascal TTECommand* TTEView::DoMakeEditCommand(CmdNumber aCmdNumber)
  1406. {
  1407.     TTECommand * aTECommand = NULL;
  1408.  
  1409.     switch (aCmdNumber)
  1410.     {
  1411.         case cCut:
  1412.         case cCopy:
  1413.             aTECommand = new TTECutCopyCommand;
  1414.             ((TTECutCopyCommand*)aTECommand)->ITECutCopyCommand(this, aCmdNumber);
  1415.             break;
  1416.             
  1417.         case cPaste:
  1418.             aTECommand = new TTEPasteCommand;
  1419.             ((TTEPasteCommand*)aTECommand)->ITEPasteCommand(this);
  1420.             break;
  1421.             
  1422.         case cClear:
  1423.             aTECommand = new TTECommand;
  1424.             aTECommand->ITECommand(this, aCmdNumber, TRUE);
  1425.             break;
  1426.  
  1427.     }
  1428.     
  1429.     return aTECommand;
  1430. }
  1431.  
  1432. //--------------------------------------------------------------------------------------------------
  1433. #pragma segment TERes
  1434.  
  1435. pascal TTEStyleCommand* TTEView::DoMakeStyleCommand(const TextStyle& aStyle,
  1436.                                                     CmdNumber itsCmdNumber,
  1437.                                                     short itsMode)
  1438. {
  1439.     TTEStyleCommand * aTEStyleCommand = new TTEStyleCommand;
  1440.  
  1441.     aTEStyleCommand->ITEStyleCommand(this, aStyle, itsCmdNumber, itsMode);
  1442.     return aTEStyleCommand;
  1443. }
  1444.  
  1445. //--------------------------------------------------------------------------------------------------
  1446. #pragma segment TERes
  1447.  
  1448. pascal TTETypingCommand* TTEView::DoMakeTypingCommand(short ch)
  1449. {
  1450.     TTETypingCommand * aTypingCommand = new TTETypingCommand;
  1451.  
  1452.     aTypingCommand->ITETypingCommand(this, ch);
  1453.     return aTypingCommand;
  1454. }
  1455.  
  1456. //--------------------------------------------------------------------------------------------------
  1457. #pragma segment TESelCommand
  1458.  
  1459. pascal void TTEView::DoMenuCommand(CmdNumber aCmdNumber)// override 
  1460. {
  1461.     long nChars;
  1462.     ResType dataType = '%%%%';
  1463.  
  1464.     switch (aCmdNumber)
  1465.     {
  1466.         case cCut:
  1467.         case cCopy:
  1468.         case cClear:
  1469.             this->PostCommand(this->DoMakeEditCommand(aCmdNumber));
  1470.             break;
  1471.  
  1472.         case cPaste:
  1473.             //!!! dataType is never used by GetDataToPaste.  Should it be a parameter?
  1474.             nChars = gClipboardMgr->GetDataToPaste(NULL, dataType);
  1475.             if (nChars < 0)
  1476.             {
  1477. #if qDebug
  1478.                 ProgramBreak("Couldn't get data to paste");// ???
  1479. #endif
  1480.  
  1481.             }
  1482.             else
  1483.             {
  1484.                 if (nChars - ((*fHTE)->selEnd - (*fHTE)->selStart) > fMaxChars - GetHandleSize(fText))
  1485.                     StdAlert(phTooManyChars);
  1486.                 else
  1487.                     this->PostCommand(this->DoMakeEditCommand(aCmdNumber));
  1488.             }
  1489.             break;
  1490.  
  1491.         case cSelectAll:
  1492.             if (this->Focus())
  1493.             {
  1494.                 TESetSelect(0, (**fHTE).teLength, fHTE);
  1495.                 this->DoneTyping();
  1496.                 fSpecsChanged = TRUE;
  1497.                 this->ScrollSelectionIntoView();
  1498.             }
  1499.             break;
  1500.  
  1501.         default:
  1502.             inherited::DoMenuCommand(aCmdNumber);
  1503.             break;
  1504.     }
  1505. }
  1506.  
  1507. //--------------------------------------------------------------------------------------------------
  1508. #pragma segment TERes
  1509.  
  1510. pascal void TTEView::DoMouseCommand(VPoint& theMouse,
  1511.                                     TToolboxEvent* event,
  1512.                                     Point)        // override 
  1513. {
  1514.     if (this->Focus() && this->IsVisible())
  1515.     {
  1516.         pCurrTEView = this;                        // So the global clikLoop routine can forward
  1517.         this->DoneTyping();                        // Mousedown terminates the Typing command 
  1518.         fSpecsChanged = TRUE;
  1519.         TEClick(this->ViewToQDPt(theMouse), event->fShiftKey, fHTE);
  1520.  
  1521.         // …force a re-focus b/c the focusing in ClikLoop clips down to the destrect. 
  1522.         if (this->IsFocused())
  1523.             this->InvalidateFocus();
  1524.  
  1525.         if (fIdleFreq == kMaxIdleTime)
  1526.             this->SetIdleFreq(0);                // Idle ASAP 
  1527.     }
  1528. }
  1529.  
  1530. //--------------------------------------------------------------------------------------------------
  1531. #pragma segment TENonRes
  1532.  
  1533. pascal void TTEView::DoneTyping(void)
  1534. {
  1535.     if (fTypingCommand != NULL)
  1536.         fTypingCommand->CompleteTyping();
  1537. }
  1538.  
  1539. //--------------------------------------------------------------------------------------------------
  1540. #pragma segment TEPrint
  1541.  
  1542. pascal void TTEView::DoSetPageOffset(const VPoint& coord)// override 
  1543.  
  1544. {
  1545.     inherited::DoSetPageOffset(coord);
  1546.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  1547.         if (coord[vhs] == 0)
  1548.             gPageOffset[vhs] = gPageOffset[vhs] + fInset[topLeft][vhs];
  1549. }
  1550.  
  1551. //--------------------------------------------------------------------------------------------------
  1552. #pragma segment TERes
  1553.  
  1554. pascal void TTEView::DoSetupMenus(void)            // override 
  1555. {
  1556.     Boolean manyChars;
  1557.  
  1558.     inherited::DoSetupMenus();
  1559.  
  1560.     manyChars = (**fHTE).selStart < (**fHTE).selEnd;
  1561.     if (!MemSpaceIsLow())
  1562.     {
  1563.         if (fAcceptsChanges)                    // One way or another, we can paste text 
  1564.             gClipboardMgr->CanPaste('TEXT');    // If styles exist, all the better 
  1565.  
  1566.         Enable(cCopy, manyChars);
  1567.     }
  1568.     Enable(cSelectAll, (**fHTE).teLength > 0);
  1569.  
  1570.     /* We enable Cut even if space is low, since it's nice to be able to rescue some of
  1571.       the stuff you have to delete even if space is low.  Note that it is possible to
  1572.       get into the "can't do any commands" situation as a result.  You should be able
  1573.       to close and save the big document, then save the rescued text elsewhere, however. */
  1574.  
  1575.     Enable(cCut, manyChars && fAcceptsChanges);
  1576.     Enable(cClear, manyChars && fAcceptsChanges);
  1577. }
  1578.  
  1579. //--------------------------------------------------------------------------------------------------
  1580. #pragma segment TERes
  1581.  
  1582. pascal void TTEView::Draw(const VRect& area)    // override 
  1583. {
  1584.     Rect QDArea;
  1585.     Boolean hideSelection;
  1586.  
  1587.     hideSelection = (gPrinting || gDrawingPictScrap) && ((Boolean)(**fHTE).active);
  1588.     if (hideSelection)
  1589.     {
  1590.         // …prevent selection from being drawn. 
  1591. #if qDebug
  1592.         UseTempRgn("TTEView.Draw");
  1593. #endif
  1594.  
  1595.         GetClip(gTempRgn);
  1596.         ClipRect(gZeroRect);
  1597.         TEDeactivate(fHTE);
  1598.         SetClip(gTempRgn);
  1599.     }
  1600.  
  1601.     this->ViewToQDRect(area, QDArea);
  1602.     TEUpdate(QDArea, fHTE);                        /* normal screen update handled by TextEdit
  1603.                                                   directly */
  1604.  
  1605.     if (hideSelection)
  1606.     {
  1607.         GetClip(gTempRgn);
  1608.         ClipRect(gZeroRect);
  1609.         TEActivate(fHTE);
  1610.         SetClip(gTempRgn);
  1611. #if qDebug
  1612.         DoneWithTempRgn();
  1613. #endif
  1614.  
  1615.     }
  1616.  
  1617.     inherited::Draw(area);
  1618. }
  1619.  
  1620. //--------------------------------------------------------------------------------------------------
  1621. #pragma segment TENonRes
  1622.  
  1623. pascal void TTEView::ExtractStyles(TEStyleHandle& theStyles,
  1624.                                    STHandle& theElements)
  1625. {
  1626.     theStyles = GetStylHandle(fHTE);
  1627.     theElements = (**theStyles).styleTab;
  1628. }
  1629.  
  1630. //--------------------------------------------------------------------------------------------------
  1631. #pragma segment TENonRes
  1632.  
  1633. pascal Handle TTEView::ExtractText(void)
  1634. {
  1635.     return fText;
  1636. }
  1637.  
  1638. //--------------------------------------------------------------------------------------------------
  1639. #pragma segment TENonRes
  1640.  
  1641. pascal void TTEView::GetPrintExtent(VRect& printExtent)// override 
  1642. {
  1643.     inherited::GetPrintExtent(printExtent);
  1644.  
  1645.     printExtent[topLeft] += fInset[topLeft];
  1646.     printExtent[botRight] -= fInset[botRight];
  1647. }
  1648.  
  1649. //--------------------------------------------------------------------------------------------------
  1650. #pragma segment TERes
  1651. pascal void TTEView::GetSelectionString(Str255& selection)
  1652. //!!! Modelled after TEditText.GetText 
  1653. {
  1654.     short start;
  1655.     short length;
  1656.     Handle theChars;
  1657.  
  1658.     selection = "";
  1659.     theChars = fText;
  1660.     if ((theChars != NULL) && (fHTE != NULL))
  1661.     {
  1662.         start = (**fHTE).selStart;
  1663.         length = (**fHTE).selEnd - start;
  1664.         length = (short)Min(255, length);        //!!! long->short
  1665.         if (length > 0)
  1666.         {
  1667.             selection[0] = ((char)(length));
  1668.             BlockMove((Ptr)((*theChars) + start), (Ptr)(&selection + 1), length);
  1669.         }
  1670.     }
  1671. }
  1672.  
  1673. //--------------------------------------------------------------------------------------------------
  1674. #pragma segment TEClipboard
  1675.  
  1676. pascal long TTEView::GivePasteData(Handle aDataHandle,
  1677.                                    ResType dataType)// override 
  1678. {
  1679.     short oldStart;
  1680.     short oldEnd;
  1681.     long aSize = 0;
  1682.     Handle aHandle = NULL;
  1683.     OSErr err;
  1684.     Boolean savedPerm = FALSE;
  1685.     FailInfo fi;
  1686.     SignedByte savedState;
  1687.  
  1688.     VOLATILE(aHandle);
  1689.  
  1690.     if (fi.Try())
  1691.     {
  1692.         if (dataType == 'TEXT')
  1693.         {
  1694.             aSize = GetHandleSize(fText);
  1695.             if (aDataHandle != NULL)
  1696.             {
  1697.                 SetPermHandleSize(aDataHandle, aSize);// Don't forget. This can fail 
  1698.                 BlockMove((*fText), (*aDataHandle), aSize);
  1699.             }
  1700.         }
  1701.         else if (dataType == 'styl')
  1702.         {
  1703.             if (fStyleType == kWithStyle)
  1704.                 if (!SpaceForStyles(0, MAXINT))
  1705.                     Failure(noErr, 0);            // We'll accept this error in worst case 
  1706.                 else
  1707.                 {
  1708.                     oldStart = (**fHTE).selStart;
  1709.                     oldEnd = (**fHTE).selEnd;
  1710.                     SetSelect(0, MAXINT, fHTE);
  1711.                     aHandle = (Handle)GetStylScrap(fHTE);
  1712.                     SetSelect(oldStart, oldEnd, fHTE);
  1713.  
  1714.                     if (aHandle != NULL)
  1715.                     {
  1716.                         aSize = GetHandleSize(aHandle);
  1717.                         if (aDataHandle != NULL)
  1718.                         {
  1719.                             savedPerm = PermAllocation(TRUE);
  1720.                             // Try to prevent fragmentation, in case can't move while we're copying it! 
  1721.                             savedState = LockHandleHigh(aHandle);
  1722.                             // Copy styles into user-supplied handle 
  1723.                             err = PtrToXHand((*aHandle), aDataHandle, aSize);
  1724.                             HSetState(aHandle, savedState);// Okay for it to move again 
  1725.                             savedPerm = PermAllocation(savedPerm);
  1726.                             if (err != noErr)    // Maybe enough for one copy, but not two! 
  1727.                                 Failure(phStylesTooBig, phStylesTooBig + msgAlert);
  1728.                         }
  1729.                         aHandle = DisposeIfHandle(aHandle);
  1730.                     }
  1731.                     else if (aDataHandle != NULL)// Hmm. There _was_ enough memory, but the 
  1732.                         Failure(phStylesTooBig, phStylesTooBig + msgAlert);/* …heap is probably pretty
  1733.                                                   fragmented */
  1734.  
  1735.                 }
  1736.         }
  1737.         else
  1738.             Failure(noTypeErr, 0);
  1739.  
  1740.         FailSpaceIsLow();
  1741.         fi.Success();
  1742.     }
  1743.     else    // Recover
  1744.     {
  1745.         aHandle = DisposeIfHandle(aHandle);
  1746.         fi.ReSignal();
  1747.     }
  1748.     return aSize;
  1749. }
  1750.  
  1751. //--------------------------------------------------------------------------------------------------
  1752. #pragma segment TENonRes
  1753. //!!! Put this routine somewhere else
  1754.  
  1755. pascal Boolean IsTEFeatureFlagAvailable(void)
  1756. // TEFeatureFlag is only available as of System 6.0.5 and better, TE version 4 and better 
  1757. {
  1758.     return (gConfiguration.systemVersion >= 0x605) && (gConfiguration.teVersion >= gestaltTE4);
  1759. }
  1760.  
  1761. //--------------------------------------------------------------------------------------------------
  1762. #pragma segment TEOpen
  1763.  
  1764. pascal void TTEView::MakeTERecord(void)
  1765. {
  1766.     TEHandle anHTE;
  1767.     GrafPtr oldPort;
  1768.     FailInfo fi;
  1769.     TextStyle aTextStyle;
  1770.  
  1771.     GetPort(oldPort);
  1772.     SetPort(gWorkPort);
  1773.     aTextStyle = fTextStyle;
  1774.     SetPortTextStyle(aTextStyle);
  1775.  
  1776.     Rect dest(fInset[topLeft], fSize - fInset[botRight]);
  1777.  
  1778.     if (fStyleType == kWithStyle)
  1779.         anHTE = TEStylNew(dest, dest);            // Open a styled record if requested 
  1780.     else
  1781.         anHTE = TENew(dest, dest);                // …otherwise, do it the old way 
  1782.  
  1783.     SetPort(oldPort);
  1784.  
  1785.     if (fi.Try())                        // In case we couldn't create the TEHandle. 
  1786.     {
  1787.         FailNIL(anHTE);                            // Make sure we actually created one 
  1788.         fHTE = anHTE;                            // We did, so save off TE handle 
  1789.         gDefClikLoopProc = (ProcPtr)(**anHTE).clikLoop;// Just in case we want to restore it… 
  1790.         // Note that the system call SetClikLoop 
  1791.         // _cannot_ be used to set the clikProc of 
  1792.         // the TERecord. This is because the default 
  1793.         // clikproc does not follow the Pascal Parameter 
  1794.         // passing conventions that this procedure expects. 
  1795.  
  1796.         this->SetJustification(fJustification, kDontRedraw);// Set justification to requested value 
  1797.         this->ChangeWrap(fAutoWrap, FALSE);            // Install auto wrap (or CR only) 
  1798.         FailNoReserve();                        // Got to have some reserve tank 
  1799.         fi.Success();
  1800.     }
  1801.     else    // Recover
  1802.     {
  1803.         this->Free();
  1804.         fi.ReSignal();
  1805.     }
  1806.  
  1807.     this->BeInPort(this->GetGrafPort());        // Associate with real port 
  1808. }
  1809.  
  1810. //--------------------------------------------------------------------------------------------------
  1811. #pragma segment TERes
  1812.  
  1813. pascal short TTEView::OffsetToLine(short offset)
  1814. {
  1815.     TERec & theTERec = **fHTE;
  1816.  
  1817.     if (theTERec.nLines <= 1)
  1818.         return 0;
  1819.     else
  1820.     {
  1821.         short i = theTERec.nLines - 1;
  1822.         while (theTERec.lineStarts[i] > offset)
  1823.             --i;
  1824.         return i;
  1825.     }
  1826. }
  1827.  
  1828. //--------------------------------------------------------------------------------------------------
  1829. #pragma segment TERes
  1830.  
  1831. pascal short TTEView::OffsetToLineStart(short offset)
  1832. {
  1833.     if ((**fHTE).nLines <= 1)
  1834.         return 0;
  1835.     else
  1836.     {
  1837.         short i = this->OffsetToLine(offset);
  1838.         return (**fHTE).lineStarts[i];
  1839.     }
  1840. }
  1841.  
  1842. //--------------------------------------------------------------------------------------------------
  1843. #pragma segment TERes
  1844.  
  1845. pascal short TTEView::OffsetToLineEnd(short offset)
  1846. {
  1847.     TERec & theTERec = **fHTE;
  1848.  
  1849.     if (theTERec.nLines <= 1)
  1850.         return theTERec.teLength;
  1851.     else
  1852.     {
  1853.         short i = theTERec.nLines - 1;
  1854.         while (theTERec.lineStarts[i] > offset)
  1855.             --i;
  1856.         if (i < theTERec.nLines - 1)
  1857.             return (theTERec.lineStarts[i + 1] - 1);
  1858.         else
  1859.             return theTERec.teLength;
  1860.     }
  1861. }
  1862.  
  1863. //--------------------------------------------------------------------------------------------------
  1864. #pragma segment TERes
  1865.  
  1866. pascal void TTEView::OffsetToPt(short offset, VPoint& itsPoint)
  1867. {
  1868.     short height;
  1869.     Point thePoint;
  1870.     TextStyle theStyle;
  1871.     short ascent;
  1872.  
  1873.     TEGetStyle(offset, theStyle, height, ascent, fHTE);
  1874.  
  1875.     if ((**fHTE).teLength <= 0)                    /* Through System 6.0.4 TE TEGetPoint returns
  1876.                                                   bogus numbers when the character count is
  1877.                                                   0. */
  1878.  
  1879.         SetPt(thePoint, (short)fInset.left, (short)fInset.top);//!!! VCoordinate->short
  1880.     else
  1881.         thePoint = TEGetPoint(offset, fHTE);
  1882.     thePoint.v = thePoint.v - height + ascent;
  1883.  
  1884.     this->QDToViewPt(thePoint, itsPoint);
  1885. }
  1886.  
  1887. //--------------------------------------------------------------------------------------------------
  1888. #pragma segment TERes
  1889.  
  1890. pascal short TTEView::PtToOffset(const VPoint& aPoint)
  1891. {
  1892.     return TEGetOffset(this->ViewToQDPt(aPoint), fHTE);
  1893. }
  1894.  
  1895. //--------------------------------------------------------------------------------------------------
  1896. #pragma segment TERes
  1897.  
  1898. pascal void TTEView::RecalcText(void)
  1899. {
  1900.     TECalText(fHTE);
  1901. }
  1902.  
  1903. //--------------------------------------------------------------------------------------------------
  1904. #pragma segment TENonRes
  1905. pascal void TTEView::ResignedWindowTarget(void)            // override 
  1906. {
  1907. /*    if (fHTE && IsTEFeatureFlagAvailable())
  1908.     {
  1909.         TEFeatureFlag(teFOutlineHilite, TEBitSet, fHTE);
  1910.     }
  1911. */
  1912. //    this->DoHighlightSelection(hlOn,hlDim);
  1913.     this->SetActive(FALSE);
  1914.     this->DoneTyping();
  1915.     fSpecsChanged = TRUE;
  1916.  
  1917.     inherited::ResignedWindowTarget();
  1918. }
  1919.  
  1920. //--------------------------------------------------------------------------------------------------
  1921. #pragma segment TENonRes
  1922. pascal void TTEView::ResignedApplicationTarget(void)            // override 
  1923. {
  1924. /*
  1925.     if (fHTE && IsTEFeatureFlagAvailable())
  1926.     {
  1927.         TEFeatureFlag(teFOutlineHilite, TEBitSet, fHTE);
  1928.     }
  1929.     this->SetActive(FALSE);
  1930.     this->DoneTyping();
  1931.     fSpecsChanged = TRUE;
  1932. */
  1933.     inherited::ResignedApplicationTarget();
  1934. }
  1935.  
  1936. //--------------------------------------------------------------------------------------------------
  1937. #pragma segment TENonRes
  1938.  
  1939. pascal void TTEView::Resize(const VPoint& newSize,
  1940.                             Boolean invalidate)    // override 
  1941. {
  1942.     VPoint oldSize(fSize);
  1943.  
  1944.     inherited::Resize(newSize, invalidate);
  1945.     if (fHTE != NULL)
  1946.     {
  1947.         Rect r(fInset[topLeft], fSize - fInset[botRight]);
  1948.  
  1949.         Boolean needCalText = (r.right != (**fHTE).destRect.right);
  1950.  
  1951.         this->StuffTERects(r);
  1952.         if (needCalText)
  1953.         {
  1954.             this->RecalcText();
  1955.             this->SynchView(kDontRedraw);
  1956.             short actualJust = GetActualJustification(fJustification);
  1957.             if (invalidate && ((fAutoWrap && (fSize != oldSize))
  1958.                                || ((actualJust == teFlushRight) || (actualJust == teCenter))))
  1959.                 this->ForceRedraw();
  1960.         }
  1961.     }
  1962. }
  1963.  
  1964. //--------------------------------------------------------------------------------------------------
  1965. #pragma segment TERes
  1966.  
  1967. pascal void TTEView::ScrollSelectionIntoView(void)
  1968. {
  1969.     VRect selectionRect;
  1970.     VPoint minToSee;
  1971.     VRect visRect;
  1972.     VRect vSelectionRect;
  1973.  
  1974.  
  1975.     /* ??? should we have an option to walk the superviews, scrolling as many scrollers as necessary
  1976.       to reveal the selection? */
  1977.     if ((this->GetScroller(FALSE) != NULL) && this->Focus())// Can't scroll selection if we don't have 
  1978.     {
  1979.         // … a scroller! 
  1980.         if (fIdleFreq == kMaxIdleTime)
  1981.             this->SetIdleFreq(0);                // Idle ASAP 
  1982.         this->GetVisibleRect(visRect);
  1983.         this->CalcSelLoc(selectionRect);
  1984.  
  1985. #if qDebugMsg
  1986.         if (gIntenseDebugging)
  1987.         {
  1988.             fprintf(stderr, "Visible Rect was: ");
  1989.             WriteVRect(visRect);
  1990.             fprintf(stderr, "; Sel Rect was: ");
  1991.             WriteVRect(selectionRect);
  1992.             fprintf(stderr, "\n");
  1993.         }
  1994. #endif
  1995.  
  1996.         if (!visRect.Contains(selectionRect))
  1997.         {
  1998.             /* Scroll the selection into view.  accounting for the user's preference for how much to
  1999.               jump at a time with fMinAhead. */
  2000.             minToSee = VPoint(selectionRect.Length(vSel), Min(fMinAhead, fSize.h - selectionRect.left));
  2001. #if qDebug
  2002.             if (gIntenseDebugging)
  2003.             {
  2004.                 WrLblVRect("RevealRect: r", selectionRect);
  2005.                 WrLblVPt(", minToSee", minToSee);
  2006.                 fprintf(stderr, "\n");
  2007.             }
  2008. #endif
  2009.  
  2010.             this->RevealRect(selectionRect, minToSee, kRedraw);
  2011.             this->Focus();                            // Refocus in newly-scrolled position. Why???
  2012.                                                     // does our caller have a dependency on this?
  2013.         }
  2014.     }
  2015.     else if (!fAutoWrap && (fHTE != NULL))
  2016.         TESelView(fHTE);
  2017. }
  2018.  
  2019. //--------------------------------------------------------------------------------------------------
  2020. #pragma segment TENonRes
  2021.  
  2022. pascal void TTEView::SetJustification(short newJust,
  2023.                                       Boolean redraw)
  2024. {
  2025.     TESetJust(newJust, fHTE);
  2026.     fJustification = newJust;
  2027.     if (redraw)
  2028.         this->ForceRedraw();
  2029. }
  2030.  
  2031. //--------------------------------------------------------------------------------------------------
  2032. #pragma segment TENonRes
  2033.  
  2034. pascal void TTEView::SetOneStyle(short theStart,
  2035.                                  short theEnd,
  2036.                                  short theMode,
  2037.                                  const TextStyle& theStyle,
  2038.                                  Boolean redraw)
  2039. {
  2040.     short saveStart;
  2041.     short saveEnd;
  2042.     FontInfo fInfo;
  2043.     TextStyle newStyle;
  2044.     short theFontHeight;
  2045.  
  2046.  
  2047.     this->InvalidateFocus();                            // ??? THIS SHOULDN'T BE NECESSARY! ??? 
  2048.     this->Focus();
  2049.     if (fStyleType == kWithStyle)
  2050.     {
  2051.         saveStart = (**fHTE).selStart;
  2052.         saveEnd = (**fHTE).selEnd;
  2053.         SetSelect(theStart, theEnd, fHTE);
  2054.         TESetStyle(theMode, theStyle, redraw, fHTE);
  2055.         SetSelect(saveStart, saveEnd, fHTE);
  2056.     }
  2057.     else
  2058.     {
  2059.         if (theMode == doAll)
  2060.             newStyle = theStyle;
  2061.         else
  2062.         {
  2063.             newStyle = fTextStyle;
  2064.             if (((theMode) & doFont) != 0)
  2065.             {
  2066.                 newStyle.tsFont = theStyle.tsFont;
  2067.  
  2068.                 KeyScript(Font2Script(newStyle.tsFont));// …keybd input system to match new font 
  2069.             }
  2070.             if (((theMode) & doFace) != 0)
  2071.                 newStyle.tsFace = theStyle.tsFace;
  2072.             if (((theMode) & doColor) != 0)
  2073.                 newStyle.tsColor = theStyle.tsColor;
  2074.             if (((theMode) & addSize) != 0)
  2075.                 newStyle.tsSize = newStyle.tsSize + theStyle.tsSize;
  2076.             else if (((theMode) & doSize) != 0)
  2077.                 newStyle.tsSize = theStyle.tsSize;
  2078.         }
  2079.  
  2080.         GetTextStyleFontInfo(newStyle, fInfo, theFontHeight);/* Need to get font's height and
  2081.                                                   ascent. */
  2082.  
  2083.         {
  2084.             TERec & theTERec = **fHTE;
  2085.     
  2086.             theTERec.txSize = newStyle.tsSize;
  2087.             theTERec.txFont = newStyle.tsFont;
  2088.             theTERec.txFace = newStyle.tsFace;
  2089.             theTERec.fontAscent = fInfo.ascent;
  2090.             theTERec.lineHeight = theFontHeight;
  2091.         }
  2092.         SetIfColor(newStyle.tsColor);
  2093.  
  2094.         fTextStyle = newStyle;
  2095.     }
  2096.  
  2097.     if (TRUE                                    /* (fStyleType == kWithoutStyle) || (theStart != theEnd) */)
  2098.     {
  2099.         this->RecalcText();
  2100.         this->SynchView(redraw && (fStyleType == kWithStyle));
  2101.         if (redraw && (fStyleType == kWithoutStyle))
  2102.             this->ForceRedraw();
  2103.     }
  2104.     fSpecsChanged = TRUE;
  2105. }
  2106.  
  2107. //--------------------------------------------------------------------------------------------------
  2108. #pragma segment TENonRes
  2109.  
  2110. pascal void TTEView::SetText(const Str255& theText)
  2111. {
  2112.     if (fHTE != NULL)                            // If we're replacing text, styles are kaput
  2113.     {
  2114.         Handle    theTextHandle;
  2115.         Str255    tempString = theText;
  2116.  
  2117.         FailOSErr(PtrToHand((Ptr)&(tempString[1]), theTextHandle, tempString.Length()));
  2118.         this->StuffText(theTextHandle);
  2119.     }
  2120. }
  2121.  
  2122. //--------------------------------------------------------------------------------------------------
  2123. #pragma segment TENonRes
  2124.  
  2125. pascal void TTEView::ShowReverted(void)            // override 
  2126. {
  2127.     this->RecalcText();
  2128.     fLastHeight = 0;
  2129.     fLastWidth = 0;
  2130.     inherited::ShowReverted();
  2131. }
  2132.  
  2133. //--------------------------------------------------------------------------------------------------
  2134. #pragma segment TENonRes
  2135.  
  2136. pascal Boolean TTEView::SpaceForStyles(long rangeStart,
  2137.                                        long rangeEnd)
  2138. {
  2139.     FailInfo fi;
  2140.     Handle h;
  2141.     Boolean result = FALSE;
  2142.  
  2143.     if (fi.Try())
  2144.     {
  2145.         h = NewPermHandle(TENumStyles(rangeStart, rangeEnd, fHTE) * sizeof(ScrpSTElement) + 2);
  2146.  
  2147.         h = DisposeIfHandle(h);                    // Release memory back to the system 
  2148.         result = TRUE;
  2149.         fi.Success();
  2150.     }
  2151.     else                                        // Recover. Don't resignal in this case
  2152.         StdAlert(phStylesTooBig);
  2153.  
  2154.     return result;
  2155. }
  2156.  
  2157. //--------------------------------------------------------------------------------------------------
  2158. #pragma segment TENonRes
  2159.  
  2160. pascal void TTEView::StuffStyles(TEStyleHandle theStyles,
  2161.                                  STHandle theElements)
  2162. {
  2163.     LHHandle oldLineHeights;
  2164.     NullStHandle theNullStyles;
  2165.     StScrpHandle theScrpHandle;
  2166.  
  2167.     if ((fStyleType == kWithStyle) && (fHTE != NULL))
  2168.     {
  2169.         {
  2170.             TEStyleHandle oldStyles = GetStylHandle(fHTE);
  2171.             TEStyleRec & theTEStyleRec = **oldStyles;
  2172.     
  2173.             STHandle oldElements = theTEStyleRec.styleTab;
  2174.             oldLineHeights = theTEStyleRec.lhTab;
  2175.             theNullStyles = theTEStyleRec.nullStyle;
  2176.             theScrpHandle = (**(theTEStyleRec.nullStyle)).nullScrap;
  2177.  
  2178.             oldElements = (STHandle)DisposeIfHandle((Handle)oldElements);
  2179.         }
  2180.  
  2181.         {
  2182.             TEStyleRec & theTEStyleRec = **theStyles;
  2183.  
  2184.             theTEStyleRec.styleTab = theElements;    // Replace STElements handle 
  2185.             theTEStyleRec.lhTab = oldLineHeights;    // Replace line heights table handle 
  2186.             theTEStyleRec.nullStyle = theNullStyles;// Replace null style handle 
  2187.             (**(theTEStyleRec.nullStyle)).nullScrap = theScrpHandle;
  2188.             theTEStyleRec.teRefCon = ((long)this);    // store ourselves as the refcon reference 
  2189.         }
  2190.  
  2191.         // NOTE!! SetStylHandle will dispose of oldStyles for us! 
  2192.         SetStylHandle(theStyles, fHTE);
  2193.  
  2194.         this->RecalcText();
  2195.     }
  2196. }
  2197.  
  2198. //--------------------------------------------------------------------------------------------------
  2199. #pragma segment TENonRes
  2200.  
  2201. pascal void TTEView::StuffText(Handle theText)
  2202. {
  2203.     if (fHTE)                                    // If we're replacing text, styles are kaput
  2204.     {
  2205.         long textLength = GetHandleSize(theText);    // Check size of new text 
  2206.         if (textLength > fMaxChars)
  2207.         {
  2208. #if qDebug
  2209.             ProgramBreak("Text size exceeds maximum for this view");
  2210. #endif
  2211.             Failure(minErr, 0);                    // ??? Assign a message 
  2212.         }
  2213.  
  2214.         if (fSavedTEHandle != theText)
  2215.         {
  2216.             fSavedTEHandle = DisposeIfHandle(fSavedTEHandle);/* …we have no choice but to dispose
  2217.                                                   it */
  2218.             fSavedTEHandle = (**fHTE).hText;    // Save existing handle 
  2219.         }
  2220.  
  2221.         (**fHTE).hText = theText;                // Install new handle 
  2222.         fText = theText;                        // Make a local copy, too 
  2223.         (**fHTE).teLength = (short)textLength;    // Tell TE how long we are  //!!! long->short
  2224.  
  2225.         if (fStyleType == kWithStyle)            // Fix for styled TE. Yuk. 
  2226.         {
  2227.             TEStyleHandle styles = GetStylHandle(fHTE);
  2228.             {
  2229.                 TEStyleRec& aTEStyleRec = **styles;
  2230.                 aTEStyleRec.runs[1].startChar = (**fHTE).teLength + 1;
  2231.                 aTEStyleRec.nRuns = 1;
  2232.                 aTEStyleRec.nStyles = 1;
  2233.                 // Thanks to map 
  2234.             }
  2235.         }
  2236.     }
  2237. }
  2238.  
  2239. //--------------------------------------------------------------------------------------------------
  2240. #pragma segment TENonRes
  2241.  
  2242. pascal void TTEView::StuffTERects(const Rect& newTERect)
  2243. {
  2244.     FontInfo aFontInfo;
  2245.     Rect localRect;
  2246.  
  2247.     GetFontInfo(aFontInfo);
  2248.  
  2249.     localRect = newTERect;
  2250.     localRect.right = (short)Max(localRect.right, localRect.left + aFontInfo.widMax);/* IM says must be at least one char wide //!!! long->short
  2251.                                                   and suggests 20 pixels.  We just check for one char.  ??? can this change in newer TE Vers? */
  2252.  
  2253.     (**fHTE).destRect = localRect;
  2254.     (**fHTE).viewRect = localRect;
  2255. }
  2256.  
  2257. //--------------------------------------------------------------------------------------------------
  2258. #pragma segment TERes
  2259.  
  2260. pascal void TTEView::SynchView(Boolean redraw)
  2261.  
  2262. {
  2263.     const short kInsertionBarWidth = 1;            /* We all _KNOW_ an insertion bar is one
  2264.                                                   pixel wide right? */
  2265.     VRect aRect;
  2266.     long theHeight;
  2267.     long theWidth;
  2268.     Boolean doRealWidth;
  2269.  
  2270.     theHeight = this->CalcRealHeight();
  2271.  
  2272.     doRealWidth = (fSizeDeterminer[hSel] == sizeVariable) &&!fStyleType &&!fAutoWrap;
  2273.     if (doRealWidth)
  2274.         theWidth = this->CalcRealWidth() + kInsertionBarWidth * 2;
  2275.  
  2276.     if ((fLastHeight != theHeight) || (doRealWidth && (fLastWidth != theWidth)))
  2277.     {
  2278.         if (doRealWidth)
  2279.             fLastWidth = theWidth;                /* Width is expensive to calculate. Cache for
  2280.                                                   CalcMinSize */
  2281.  
  2282.         this->AdjustSize();                        // may need to grow view 
  2283.         fLastHeight = theHeight;                // Remember new height value 
  2284.     }
  2285.  
  2286.     if (redraw && this->Focus())
  2287.     /* First, make sure selection is visible (this conveniently focuses). Then,
  2288.       repair any extra feedback which TextEdit may have mashed. */
  2289.     {
  2290.         this->ScrollSelectionIntoView();
  2291.         this->DoHighlightSelection(hlOff, fHLDesired);
  2292.         if (fPrintHandler != NULL)
  2293.         {
  2294.             this->GetDrawableRect(aRect);
  2295.             this->DoDrawPrintFeedback(aRect);
  2296.         }
  2297.     }
  2298. }
  2299.  
  2300. //--------------------------------------------------------------------------------------------------
  2301. #pragma segment TENonRes
  2302.  
  2303. pascal void TTEView::WriteToDeskScrap(void)        // override 
  2304. {
  2305.     Handle aHandle;
  2306.  
  2307.  
  2308.     FailOSErr(gClipboardMgr->PutDeskScrapData('TEXT', fText));
  2309.  
  2310.     if ((fStyleType == kWithStyle) && this->SpaceForStyles(0, MAXINT))
  2311.     {
  2312.         SetSelect(0, MAXINT, fHTE);
  2313.         aHandle = (Handle)(GetStylScrap(fHTE));
  2314.         FailNIL(aHandle);
  2315.         FailOSErr(gClipboardMgr->PutDeskScrapData('styl', aHandle));
  2316.     }
  2317. }
  2318.  
  2319. //--------------------------------------------------------------------------------------------------
  2320. #pragma segment TERes
  2321. pascal void TTEView::SetActive(Boolean state)
  2322. {
  2323.     if ((fHTE != NULL) && this->Focus())        // Try to focus because TEActivate/TEDeactivate may draw 
  2324.         if (state)
  2325.             TEActivate(fHTE);
  2326.         else
  2327.         {
  2328.             TEDeactivate(fHTE);
  2329.         }
  2330. }
  2331.  
  2332. //--------------------------------------------------------------------------------------------------
  2333. #pragma segment TERes
  2334.  
  2335. pascal void TTEView::SetEnable(Boolean state)
  2336. {
  2337.     if (state && (fIdleFreq == kMaxIdleTime))
  2338.         this->SetIdleFreq(0);                    // Get correct idle set ASAP 
  2339.  
  2340.     inherited::SetEnable(state);
  2341. }
  2342.  
  2343. //--------------------------------------------------------------------------------------------------
  2344. #pragma segment TERes
  2345. pascal Boolean TTEView::WantToBecomeTarget(void)// override 
  2346. {
  2347.     return TRUE;
  2348. }
  2349.  
  2350. //--------------------------------------------------------------------------------------------------
  2351. #pragma segment TERes
  2352.  
  2353. pascal Boolean TTEView::WordBounds(short charPos,
  2354.                                    short& wordStart,
  2355.                                    short& wordEnd)
  2356. {
  2357.     OffsetTable offs;
  2358.     short i;
  2359.  
  2360.     wordStart = charPos;
  2361.     wordEnd = charPos;
  2362.  
  2363.     if ((charPos < 0) || (charPos > (**fHTE).teLength - 1))
  2364.         return FALSE;
  2365.  
  2366.     do
  2367.     {
  2368.         i = CharByte((*fText), charPos++);
  2369.     } while ((i == smFirstByte) || (i == smMiddleByte));    // while ((i != smSingleByte) && (i != smLastByte));
  2370.  
  2371.     FindWord((*fText), (**fHTE).teLength, --charPos, TRUE, NULL, offs);
  2372.     wordStart = (short)Min(offs[0].offFirst, offs[0].offSecond - 1);//!!! long->short
  2373.     wordEnd = (short)Max(offs[0].offFirst, offs[0].offSecond - 1);//!!! long->short
  2374.     return ((wordStart < wordEnd) || (CharType((*fText), wordStart) % 8 != smCharPunct));
  2375.  
  2376. }
  2377.  
  2378. //--------------------------------------------------------------------------------------------------
  2379. #pragma segment TEFields
  2380.  
  2381. pascal void TTEView::Fields(TObject* obj)        // override 
  2382. {
  2383.     obj->DoToField("TTEView", NULL, bClass);
  2384.     obj->DoToField("fHTE", &fHTE, bTEHandle);
  2385.     obj->DoToField("fText", &fText, bHandle);
  2386.     obj->DoToField("fSavedTEHandle", &fSavedTEHandle, bHandle);
  2387.     obj->DoToField("fInset", &fInset, bRect);
  2388.     obj->DoToField("fKeyCmdNumber", &fKeyCmdNumber, bCmdNumber);
  2389.     obj->DoToField("fMaxChars", &fMaxChars, bInteger);
  2390.     obj->DoToField("fLastHeight", &fLastHeight, bLongInt);
  2391.     obj->DoToField("fLastWidth", &fLastWidth, bLongInt);
  2392.     obj->DoToField("fTypingCommand", &fTypingCommand, bObject);
  2393.     obj->DoToField("fTextStyle", &fTextStyle, bTextStyle);
  2394.     obj->DoToField("fJustification", &fJustification, bInteger);
  2395.     obj->DoToField("fAcceptsChanges", &fAcceptsChanges, bBoolean);
  2396.     obj->DoToField("fStyleType", &fStyleType, bBoolean);
  2397.     obj->DoToField("fAutoWrap", &fAutoWrap, bBoolean);
  2398.     obj->DoToField("fFreeText", &fFreeText, bBoolean);
  2399.     obj->DoToField("fSpecsChanged", &fSpecsChanged, bBoolean);
  2400.     obj->DoToField("fLastLine", &fLastLine, bInteger);
  2401.     obj->DoToField("fLastPageBreak", &fLastPageBreak, bInteger);
  2402.     obj->DoToField("fControlChars", &fControlChars, bHexLongInt);
  2403.     obj->DoToField("fMinAhead", &fMinAhead, bInteger);
  2404.  
  2405.     inherited::Fields(obj);
  2406. }
  2407.  
  2408.